package com.yfbao.horizon.encrypt.utils;


import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * DES加密说明
 * <p>
 * DES是一种对称加密算法，对称加密即：加密和解密使用相同密钥的算法。
 * <p>
 * 注意：DES加密和解密过程中，密钥长度必须是8的倍数;
 */
@Slf4j
public class DESUtils {
    private static final String DES = "DES";
    private static final String EN_CODING = "UTF-8";

    /**
     * 加密过程
     *
     * @param clearText 明文
     * @param key       秘钥
     * @return base64后密文str
     */
    public static String encrypt(String clearText, String key) {
        try {
            return encrypt(clearText.getBytes(EN_CODING), key);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 加密过程
     *
     * @param clearText 明文
     * @param key       秘钥
     * @return base64后密文str
     */
    public static String encrypt(byte[] clearText, String key) {
        try {
            // DES算法要求有一个可信任的随机数源
            SecureRandom secureRandom = new SecureRandom();
            // 创建一个DESKeySpec对象
            DESKeySpec desKeySpec = new DESKeySpec(key.getBytes());
            // 创建密匙工厂
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(DES);
            // 将密码利用密匙工厂转换成密匙
            SecretKey securekey = secretKeyFactory.generateSecret(desKeySpec);
            // 创建Cipher对象，用于完成实际加密操作
            Cipher cipher = Cipher.getInstance(DES);
            // 用密匙初始化Cipher对象
            cipher.init(Cipher.ENCRYPT_MODE, securekey, secureRandom);
            // 执行加密操作并返回密文
            return Base64.getEncoder().encodeToString(cipher.doFinal(clearText));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 解密
     *
     * @param cipherText 密文
     * @param key        秘钥 String
     * @return String
     */
    public static String decrypt(String cipherText, String key) {
        try {
            return new String(decrypt2Byte(cipherText, key));
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 解密
     *
     * @param cipherText 密文
     * @param key        秘钥 String
     * @return byte[]
     */
    public static byte[] decrypt2Byte(String cipherText, String key) {
        try {
            // DES算法要求有一个可信任的随机数源
            SecureRandom random = new SecureRandom();
            // 创建一个DESKeySpec对象
            DESKeySpec desKey = new DESKeySpec(key.getBytes());
            // 创建一个密匙工厂
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
            // 将DESKeySpec对象转换成SecretKey对象
            SecretKey securekey = keyFactory.generateSecret(desKey);
            // Cipher对象，用于完成实际解密操作
            Cipher cipher = Cipher.getInstance(DES);
            // 用密匙初始化Cipher对象
            cipher.init(Cipher.DECRYPT_MODE, securekey, random);
            // 开始解密
            return cipher.doFinal(Base64.getDecoder().decode(cipherText));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
